<?php
/**
 * User:
 * Date:
 * Time:
 */

namespace App\Common\RedisCache;


abstract class AbstractHashCache extends AbstractCache
{
    /**
     * 当前field
     * @var string
     */
    protected $field = '';
    /**
     * 是否json处理
     * @var bool
     */
    protected static $json = false;

    /**
     * 当前field生成参数
     * @param array $parameter
     * @return $this
     */
    public function setFieldParameter(array $parameter)
    {
        $this->field = $this::field($parameter);
        return $this;
    }

    /**
     * field生成方法
     * @param array $parameter
     * @return string
     */
    abstract protected static function field(array $parameter): string ;

    /**
     * 生成单条
     * @param $value
     * @return int|mixed
     */
    public function set($value)
    {
        $this->select();
        if (is_array($value)) {
            $r = $this::$client->hSet($this->key, $this->field, json_encode($value,JSON_UNESCAPED_UNICODE));
        } else {
            $r = $this::$client->hSet($this->key, $this->field, $value);
        }
        return $r;
    }

    /**
     * 批量生成
     * @param array $field [ 0 => ['rule_id' => 21, 'user_id' => 6869], 1 => ['rule_id' => 68, 'user_id'=> 21485] ...]
     * @param array $value [ 0 => 100, 1 => 200  ...]
     * @return bool
     */
    public function hMset($field, $value)
    {
        $this->select();

        $field_arr = [];
        foreach ($field as $k => $val) {
            $hash_key = $this::field($val);
            $field_arr[$hash_key] = $value[$k];
        }
        return $this::$client->hMset($this->key, $field_arr);
    }
    /**
     * 删除指定field
     * @param string $key
     * @param string $field
     * @return int
     */
    public function hDel($key = '', $field = '')
    {
        $this->select();

        if (empty($key)) {
            $key = $this->key;
        }
        if (empty($field)) {
            $field = $this->field;
        }

        return $this::$client->hDel($key, $field);
    }

    /**
     * 获取指定field
     * @param string $key
     * @param string $field
     * @return mixed|string
     */
    public function get($key = '', $field = '')
    {
        $this->select();

        if (empty($key)) {
            $key = $this->key;
        }
        if (empty($field)) {
            $field = $this->field;
        }
        $r = $this::$client->hGet($key, $field);
        if ($this::$json) {
            $r = json_decode($r, true);
        }
        return $r;
    }

    /**
     * 获取元素长度或数量
     * @param string $key
     * @return int
     */
    public function len($key = ''): int
    {
        $this->select();

        if (empty($key)) {
            $key = $this->key;
        }

        return $this::$client->hLen($key);
    }

    /**
     * 获取全部字段和值
     * @param string $key
     * @return array
     */
    public function getAll($key = '')
    {
        $this->select();

        if (empty($key)) {
            $key = $this->key;
        }
        $r = $this::$client->hGetAll($key);
        if ($this::$json) {
            foreach ($r as &$v) {
                $v = json_decode($v, true);
                unset($v);
            }
        }
        return $r;
    }

    /**
     * 获取所有field
     * @param string $key
     * @return array
     */
    public function hKeys($key = '')
    {
        $this->select();
        if (empty($key)) {
            $key = $this->key;
        }
        return $this::$client->hKeys($key);
    }

    /**
     * 礼物pk 使用
     * @param string $key
     * @return array
     */
    public function newGetAll($key = '')
    {
        $this->select();

        if (empty($key)) {
            $key = $this->key;
        }
        $r = $this::$client->hGetAll($key);
        return $r;
    }

    /**
     * 字段是否存在
     * @param string $key
     * @param string $field
     * @return bool
     */
    public function fieldExists($key = '', $field = '')
    {
        $this->select();

        if (empty($key)) {
            $key = $this->key;
        }
        if (empty($field)) {
            $field = $this->field;
        }
        $r = $this::$client->hExists($key, $field);

        return $r;
    }

    /**
     * field值+1
     * @param string $key
     * @param string $field
     * @return int
     */
    public function increase($key = '', $field = '')
    {
        $this->select();

        if (empty($key)) {
            $key = $this->key;
        }
        return $this->increaseByInt(1, $key, $field);
    }

    /**
     * field值-1
     * @param string $key
     * @param string $field
     * @return int
     */
    public function decrease($key = '', $field = '')
    {
        return $this->increaseByInt(-1, $key, $field);
    }

    /**
     * field值整型增量
     * @param $value
     * @param string $key
     * @param string $field
     * @return int
     */
    public function increaseByInt($value, $key = '', $field = '')
    {
        $this->select();

        if (empty($key)) {
            $key = $this->key;
        }
        if (empty($field)) {
            $field = $this->field;
        }
        $value = intval($value);

        return $this::$client->hIncrBy($key, $field, $value);
    }

    /**
     * field值浮点型增量
     * @param $value
     * @param string $key
     * @param string $field
     * @return float
     */
    public function increaseByFloat($value, $key = '', $field = '')
    {
        $this->select();

        if (empty($key)) {
            $key = $this->key;
        }
        if (empty($field)) {
            $field = $this->field;
        }
        $value = floatval($value);

        return $this::$client->hIncrByFloat($key, $field, $value);
    }

    /**
     * 获取key全部 f-v
     * @param string $k
     * @return array
     * @author AIbula
     * @date   2022/06/27
     */
    public function replaceHgetall($k = '')
    {
        if (empty($key)) {
            $k = $this->key;
        }
        $this->select();
        $val_arr = $this::$client->Hvals($k);
        $key_arr = $this::$client->Hkeys($k);
        if (!empty($val_arr)) {
            $data = array();
            foreach ($key_arr as $key => $value) {

                $data[$value] = $val_arr[$key];
            }
            return $data;
        } else {
            return [];
        }
    }
}
